package com.transmit.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.Ftp;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.transmit.conf.MyProperty;
import com.transmit.conf.propertis.DataSourceProperty;
import com.transmit.conf.propertis.DataTargetProperty;
import com.transmit.enums.CoalMineCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.File;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class TransmitDataTask {

    @Autowired
    private MyProperty myProperty;

    @Autowired
    private DataSourceProperty dataSourceProperty;

    @Autowired
    private DataTargetProperty dataTargetProperty;

    private static final Long PROJECT_ID = 1683705777884L;

    /**
     * 每天凌晨一点执行
     */
    @Scheduled(cron = "0 0 1 * * ?")
//    @Scheduled(cron = "0/10 * * * * ?")
    public void doTask() {
        // 数据根路径
        String dataRoot = myProperty.getDataRoot();
        String startDate = null;
        String endDate = null;
        // note.txt文件不存在时，上传所有的数据；否则，只上传前一天的数据
        File noteFile = new File(dataRoot + "note.txt");
        if (noteFile.exists()) {
            String yesterday = DateUtil.format(DateUtil.yesterday(), "yyyy-MM-dd");
            startDate = yesterday;
            endDate = yesterday;
        } else {
            // 创建note.txt文件
            FileUtil.touch(noteFile);
        }

        // 获取token
        String token = getToken("qixian", "f4adb45e8b367dbf024a0cef6fde7820");

        // 推送 5.2.4 GNSS 设备信息
        transmitData1(token, startDate, endDate);

        // 推送 5.3.3 GNSS 监测数据
        transmitData2(token, startDate, endDate);

        // 推送 5.3.4 GNSS 预警信息
        transmitData3(token, startDate, endDate);

        // 推送 5.3.5 预警处置信息
        transmitData4(token, startDate, endDate);

    }

    /**
     *  获取token
     */
    private String getToken(String username, String password) {
        JSONObject loginParam = new JSONObject();
        loginParam.put("username", username);
        loginParam.put("password", password);
        String loginRes = HttpUtil.post(dataSourceProperty.url + "/light3d_yiyang/user/login", loginParam.toJSONString());
        String token = JSONObject.parseObject(loginRes).getJSONObject("data").getString("token");
        return token;
    }

    /**
     *  推送 5.2.4 GNSS 设备信息
     */
    private void transmitData1(String token, String startDate, String endDate) {
        String coalMineCode = myProperty.getCoalMineCode();
        // 获取设备信息列表
        JSONArray sbxxList = getSbxxList(token, startDate, endDate);
        if (CollUtil.isEmpty(sbxxList)) {
            log.info("{}-设备信息-{}", DateUtil.now(), "没有数据");
            return;
        }

        JSONObject transmitData = new JSONObject();
        transmitData.put("send_time", DateUtil.now());
        transmitData.put("data", sbxxList.stream().map(e -> {
            JSONObject source = JSON.parseObject(JSON.toJSONString(e));
            String pointName = source.getString("pointName");
            String sn = source.getString("sn");

            JSONObject target = new JSONObject();
            target.put("equip_no", getEquipmentCode(pointName, sn));
            target.put("equip_name", pointName);
            target.put("equip_location", "");
            target.put("open_pit_no", coalMineCode);
            target.put("slope_no", "");
            target.put("installation_date", "");
            target.put("longitude", source.getDouble("longitude"));
            target.put("latitude", source.getDouble("latitude"));
            target.put("altitude", source.getDouble("altitude"));
            target.put("manufacture", "");
            target.put("equip_range", "");
            target.put("in_use", "正常".equals(source.getString("status")) ? 1 : 0);
            target.put("breakdown", "正常".equals(source.getString("status")) ? 0 : 1);
            target.put("create_time", source.getString("createTime"));
            target.put("update_time", source.getString("modifyTime"));
            return target;
        }).collect(Collectors.toList()));

        String fileName = StrUtil.format("{}_gnssbaseinfo_{}_{}.json",
                coalMineCode, DateUtil.format(new Date(), "yyyyMMddHHmmss"), RandomUtil.randomNumbers(4));

        // 现将数据文件在本地存一份
        FileUtil.writeUtf8String(transmitData.toJSONString(), getDataPath() + fileName);

        // 上传至目标服务器
        Ftp ftp = new Ftp(dataTargetProperty.host, dataTargetProperty.port, dataTargetProperty.user, dataTargetProperty.password);
        boolean upload = ftp.upload(dataTargetProperty.targetDir, fileName, new ByteArrayInputStream(transmitData.toJSONString().getBytes()));
        log.info("{}-设备信息-{}", DateUtil.now(), upload ? "推送成功" : "推送失败");
        IoUtil.close(ftp);
    }

    /**
     * 获取设备编号
     * @param pointName
     * @param sn
     * @return
     */
    private String getEquipmentCode(String pointName, String sn) {
        String coalMineCode = myProperty.getCoalMineCode();
        // 点石沟煤矿 设备编码：取SN号后两位；其他取点名称后两位
        if (CoalMineCode.DIAN_SHI_GOU.getCode().equals(coalMineCode)) {
            return coalMineCode + "020000" + getStrLastTwo(sn);
        }
        return coalMineCode + "020000" + getStrLastTwo(pointName);
    }

    /**
     * 获取字符串后两位
     * @param str
     * @return
     */
    private String getStrLastTwo(String str) {
        if (StrUtil.isBlank(str)) {
            return StrUtil.EMPTY;
        }
        if (str.length() < 2) {
            return str;
        }
        return str.substring(str.length() - 2);
    }

    private JSONArray getSbxxList(String token, String startDate, String endDate) {
        JSONObject sbxxParam = new JSONObject();
        sbxxParam.put("pageNum", 1);
        sbxxParam.put("pageSize", Integer.MAX_VALUE);
        sbxxParam.put("projectId", PROJECT_ID);
        sbxxParam.put("type", 1);
        sbxxParam.put("sceneId", dataSourceProperty.sceneId);
        sbxxParam.put("startDate", startDate);
        sbxxParam.put("endDate", endDate);
        String sbxxRes = HttpRequest.get(dataSourceProperty.url + "/light3d_yiyang/monitor/point/list")
                .header("Token", token)
                .form(sbxxParam).execute().body();
        JSONArray sbxxList = JSON.parseObject(sbxxRes).getJSONObject("data").getJSONArray("list");
        return sbxxList;
    }

    /**
     *  推送  5.3.3 GNSS 监测数据
     */
    private void transmitData2(String token, String startDate, String endDate) {
        String coalMineCode = myProperty.getCoalMineCode();
        List<JSONObject> jcsjList = new ArrayList<>();
        // 获取所有的设备信息列表，逐条推送每台设备的监测数据
        JSONArray sbxxList = getSbxxList(token, null, null);
        for (Object sbxx : sbxxList) {
            JSONObject sbxxJson = JSON.parseObject(JSON.toJSONString(sbxx));
            Long id = sbxxJson.getLong("id");
            String pointName = sbxxJson.getString("pointName");
            String sn = sbxxJson.getString("sn");

            JSONObject jcsjParam = new JSONObject();
            jcsjParam.put("pageNum", 1);
            jcsjParam.put("pageSize", Integer.MAX_VALUE);
            jcsjParam.put("projectId", PROJECT_ID);
            jcsjParam.put("pointId", id);
            jcsjParam.put("startDate", startDate);
            jcsjParam.put("endDate", endDate);
            String jcsjRes = HttpRequest.get(dataSourceProperty.url + "/light3d_yiyang/monitor/data/list")
                    .header("Token", token)
                    .form(jcsjParam).execute().body();
            JSONArray jcsjResList = JSON.parseObject(jcsjRes).getJSONObject("data").getJSONArray("list");
            for (Object e : jcsjResList) {
                JSONObject jcsjJSON = JSON.parseObject(JSON.toJSONString(e));
                JSONObject jcsj = new JSONObject();
                jcsj.put("equip_no", getEquipmentCode(pointName, sn));
                jcsj.put("monitor_time", jcsjJSON.getString("monitorTime"));
                jcsj.put("longitude", sbxxJson.getDouble("longitude"));
                jcsj.put("latitude", sbxxJson.getDouble("latitude"));
                jcsj.put("altitude", sbxxJson.getDouble("altitude"));
                jcsj.put("x_disp", jcsjJSON.getDouble("eValue"));
                jcsj.put("y_disp", jcsjJSON.getDouble("nValue"));
                jcsj.put("z_disp", jcsjJSON.getDouble("uValue"));
                jcsj.put("x_speed", jcsjJSON.getDouble("xspeed"));
                jcsj.put("y_speed", jcsjJSON.getDouble("yspeed"));
                jcsj.put("z_speed", jcsjJSON.getDouble("zspeed"));
                jcsj.put("x_acc_speed", jcsjJSON.getDouble("xaccspeed"));
                jcsj.put("y_acc_speed", jcsjJSON.getDouble("yaccspeed"));
                jcsj.put("z_acc_speed", jcsjJSON.getDouble("zaccspeed"));
                jcsjList.add(jcsj);
            }

        }

        if (CollUtil.isEmpty(jcsjList)) {
            log.info("{}-监测数据-{}", DateUtil.now(), "没有数据");
            return;
        }

        JSONObject transmitData = new JSONObject();
        transmitData.put("send_time", DateUtil.now());
        transmitData.put("data", jcsjList);

        String fileName = StrUtil.format("{}_gnssrealtime_{}_{}.json",
                coalMineCode, DateUtil.format(new Date(), "yyyyMMddHHmmss"), RandomUtil.randomNumbers(4));

        // 现将数据文件在本地存一份
        FileUtil.writeUtf8String(transmitData.toJSONString(), getDataPath() + fileName);

        // 上传至目标服务器
        Ftp ftp = new Ftp(dataTargetProperty.host, dataTargetProperty.port, dataTargetProperty.user, dataTargetProperty.password);
        boolean upload = ftp.upload(dataTargetProperty.targetDir, fileName, new ByteArrayInputStream(transmitData.toJSONString().getBytes()));
        log.info("{}-监测数据-{}", DateUtil.now(), upload ? "推送成功" : "推送失败");
        IoUtil.close(ftp);
    }

    /**
     *  推送  5.3.4 GNSS 预警信息
     */
    private void transmitData3(String token, String startDate, String endDate) {
        String coalMineCode = myProperty.getCoalMineCode();
        JSONObject yjxxParam = new JSONObject();
        yjxxParam.put("pageNum", 1);
        yjxxParam.put("pageSize", Integer.MAX_VALUE);
        yjxxParam.put("projectId", PROJECT_ID);
        yjxxParam.put("type", 1);
        yjxxParam.put("sceneId", dataSourceProperty.sceneId);
        yjxxParam.put("startDate", startDate);
        yjxxParam.put("endDate", endDate);
        String sbxxRes = HttpRequest.get(dataSourceProperty.url + "/light3d_yiyang/monitor/point/alter/list")
                .header("Token", token)
                .form(yjxxParam).execute().body();
        JSONArray yjxxList = JSON.parseObject(sbxxRes).getJSONObject("data").getJSONArray("list");

        if (CollUtil.isEmpty(yjxxList)) {
            log.info("{}-预警信息-{}", DateUtil.now(), "没有数据");
            return;
        }

        JSONObject transmitData = new JSONObject();
        transmitData.put("send_time", DateUtil.now());
        transmitData.put("data", yjxxList.stream().map(e -> {
            JSONObject source = JSON.parseObject(JSON.toJSONString(e));
            String pointName = source.getString("pointName");
            JSONObject point = source.getJSONObject("point");
            String sn = point.getString("sn");

            JSONObject target = new JSONObject();
            target.put("equip_no", getEquipmentCode(pointName, sn));
            target.put("alarm_time", source.getString("alterTime"));
            target.put("alarm_update_time", source.getString("alterTime"));
            target.put("alarm_level", getAlarmLevelValue(source.getString("alterLevel")));
            String content = source.getString("content");
            String direction = content.substring(content.lastIndexOf(" ") + 1, content.lastIndexOf("方向"));
            JSONObject warningParameters = getWarningParameters(direction, point);
            target.put("warning_parameters", warningParameters);
            String alarmValue = content.substring(content.lastIndexOf("达到") + 2, content.lastIndexOf("，"));
            target.put("alarm_value", alarmValue);
            return target;
        }).collect(Collectors.toList()));

        String fileName = StrUtil.format("{}_gnssalarm_{}_{}.json",
                coalMineCode, DateUtil.format(new Date(), "yyyyMMddHHmmss"), RandomUtil.randomNumbers(4));

        // 现将数据文件在本地存一份
        FileUtil.writeUtf8String(transmitData.toJSONString(), getDataPath() + fileName);

        // 上传至目标服务器
        Ftp ftp = new Ftp(dataTargetProperty.host, dataTargetProperty.port, dataTargetProperty.user, dataTargetProperty.password);
        boolean upload = ftp.upload(dataTargetProperty.targetDir, fileName, new ByteArrayInputStream(transmitData.toJSONString().getBytes()));
        log.info("{}-预警信息-{}", DateUtil.now(), upload ? "推送成功" : "推送失败");
        IoUtil.close(ftp);
    }

    private JSONObject getWarningParameters(String direction, JSONObject point) {
        JSONObject jsonObject = new JSONObject();
        if ("X".equals(direction)) {
            jsonObject.put("eastBlue", point.getString("eastBlue"));
            jsonObject.put("eastYellow", point.getString("eastYellow"));
            jsonObject.put("eastOrange", point.getString("eastOrange"));
            jsonObject.put("eastRed", point.getString("eastRed"));
        } else if ("Y".equals(direction)) {
            jsonObject.put("northBlue", point.getString("northBlue"));
            jsonObject.put("northYellow", point.getString("northYellow"));
            jsonObject.put("northOrange", point.getString("northOrange"));
            jsonObject.put("northRed", point.getString("northRed"));
        } else if ("Z".equals(direction)) {
            jsonObject.put("upBlue", point.getString("upBlue"));
            jsonObject.put("upYellow", point.getString("upYellow"));
            jsonObject.put("upOrange", point.getString("upOrange"));
            jsonObject.put("upRed", point.getString("upRed"));
        } else if ("X_day".equals(direction)) {
            jsonObject.put("eChangeValueDayBlue", point.getString("eChangeValueDayBlue"));
            jsonObject.put("eChangeValueDayYellow", point.getString("eChangeValueDayYellow"));
            jsonObject.put("eChangeValueDayOrange", point.getString("eChangeValueDayOrange"));
            jsonObject.put("eChangeValueDayRed", point.getString("eChangeValueDayRed"));
        } else if ("Y_day".equals(direction)) {
            jsonObject.put("nChangeValueDayBlue", point.getString("nChangeValueDayBlue"));
            jsonObject.put("nChangeValueDayYellow", point.getString("nChangeValueDayYellow"));
            jsonObject.put("nChangeValueDayOrange", point.getString("nChangeValueDayOrange"));
            jsonObject.put("nChangeValueDayRed", point.getString("nChangeValueDayRed"));
        } else if ("Z_day".equals(direction)) {
            jsonObject.put("uChangeValueDayBlue", point.getString("uChangeValueDayBlue"));
            jsonObject.put("uChangeValueDayYellow", point.getString("uChangeValueDayYellow"));
            jsonObject.put("uChangeValueDayOrange", point.getString("uChangeValueDayOrange"));
            jsonObject.put("uChangeValueDayRed", point.getString("uChangeValueDayRed"));
        }
        return jsonObject;
    }

    private Integer getAlarmLevelValue(String alarmLevel) {
        if ("红色预警".equals(alarmLevel)) {
            return 1;
        } else if ("橙色预警".equals(alarmLevel)) {
            return 2;
        } else if ("黄色预警".equals(alarmLevel)) {
            return 3;
        } else if ("蓝色预警".equals(alarmLevel)) {
            return 4;
        } else {
            return 0;
        }
    }

    /**
     *  推送  5.3.5 预警处置信息
     */
    private void transmitData4(String token, String startDate, String endDate) {
        String coalMineCode = myProperty.getCoalMineCode();
        JSONObject yjxxParam = new JSONObject();
        yjxxParam.put("pageNum", 1);
        yjxxParam.put("pageSize", Integer.MAX_VALUE);
        yjxxParam.put("projectId", PROJECT_ID);
        yjxxParam.put("type", 1);
        yjxxParam.put("sceneId", dataSourceProperty.sceneId);
        yjxxParam.put("startDate", startDate);
        yjxxParam.put("endDate", endDate);
        String sbxxRes = HttpRequest.get(dataSourceProperty.url + "/light3d_yiyang/monitor/point/alter/list")
                .header("Token", token)
                .form(yjxxParam).execute().body();
        JSONArray yjxxList = JSON.parseObject(sbxxRes).getJSONObject("data").getJSONArray("list");

        if (CollUtil.isEmpty(yjxxList)) {
            log.info("{}-预警处置信息-{}", DateUtil.now(), "没有数据");
            return;
        }

        JSONObject transmitData = new JSONObject();
        transmitData.put("send_time", DateUtil.now());
        transmitData.put("data", yjxxList.stream().map(e -> {
            JSONObject source = JSON.parseObject(JSON.toJSONString(e));
            String pointName = source.getString("pointName");
            JSONObject point = source.getJSONObject("point");
            String sn = point.getString("sn");

            JSONObject target = new JSONObject();
            target.put("equip_no", getEquipmentCode(pointName, sn));
            target.put("alarm_time", source.getString("alterTime"));
            target.put("handle_time", source.getString("dealTime"));
            target.put("description", source.getString("remark"));
            return target;
        }).collect(Collectors.toList()));

        String fileName = StrUtil.format("{}_clearalarm_{}_{}.json",
                coalMineCode, DateUtil.format(new Date(), "yyyyMMddHHmmss"), RandomUtil.randomNumbers(4));

        // 现将数据文件在本地存一份
        FileUtil.writeUtf8String(transmitData.toJSONString(), getDataPath() + fileName);

        // 上传至目标服务器
        Ftp ftp = new Ftp(dataTargetProperty.host, dataTargetProperty.port, dataTargetProperty.user, dataTargetProperty.password);
        boolean upload = ftp.upload(dataTargetProperty.targetDir, fileName, new ByteArrayInputStream(transmitData.toJSONString().getBytes()));
        log.info("{}-预警处置信息-{}", DateUtil.now(), upload ? "推送成功" : "推送失败");
        IoUtil.close(ftp);
    }

    private String getDataPath() {
        return myProperty.dataRoot + DateUtil.format(new Date(), "yyyy/MM/dd/");
    }
}
